#pragma once
#include "log.hpp"
#include <string>
#include <sys/types.h>  
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <strings.h>
#include <functional>
#include "inetAddr.hpp"

using namespace LogModule;
using func_t = std::function<std::string(const std::string&, InetAddr&)>;

class Server
{
public:
//std::string ip = "192.168.8.16", uint16_t port = 8080
    Server(InetAddr addr, func_t f, std::string ip = "192.168.8.16", uint16_t port = 8080)
        :_addr(addr)
        ,_f(f)
    {}

    void Init()
    {
        // LOG((int)LogLevel::DEBUG) << _addr.Port() << " | " << _port << 
        // _addr.Ip() << " | " << _ip;
        _socketfd = socket(AF_INET, SOCK_DGRAM, 0);
        if(_socketfd < 0)
        {
            LOG((int)LogLevel::FATAL) << "套接字创建失败，服务器退出!";
            exit(1);
        }
        LOG((int)LogLevel::INFO) << "套接字创建成功!";

        //初始化
        struct sockaddr_in local;
        bzero(&local, sizeof(local));
        local.sin_family = AF_INET;
        local.sin_port = htons(_addr.Port());
        local.sin_addr.s_addr = inet_addr(_addr.Ip().c_str());

        int n = bind(_socketfd, (sockaddr*)&local, sizeof(local));
        if(n < 0)
        {
            LOG((int)LogLevel::FATAL) << "bind失败，服务器退出!";
            exit(1);
        }
        LOG((int)LogLevel::INFO) << "bind成功!";
    }

    void Start()
    {
        struct sockaddr_in peer;
        bzero(&peer, sizeof(peer));
        while (true)
        {
            char rcMessage[1000];
            socklen_t len = sizeof(peer);
            int n = recvfrom(_socketfd, rcMessage, sizeof(rcMessage) - 1, 0, (sockaddr*)&peer
            ,&len);
            if(n < 0)
            {
                LOG((int)LogLevel::FATAL) << "接收信息失败，服务器退出!";
                exit(1);
            }
            else
            {
                rcMessage[n] = 0;
            }
            // uint16_t port = ntohs(peer.sin_port);
            // char* ip = inet_ntoa(peer.sin_addr);
            InetAddr client(peer);
            // std::cout << "[" << ip << " | " << port << "]" << 
            // "client say# " << rcMessage << std::endl;

            // char sdMessage[1000];

            // n = snprintf(sdMessage, sizeof(sdMessage), "服务器收到你的消息了！");
            // sdMessage[n] = 0;
            // n = sendto(_socketfd, sdMessage, sizeof(sdMessage), 0, (sockaddr*)&peer
            // , len);
            std::string ret = _f(rcMessage, client);
            n = sendto(_socketfd, ret.c_str(), ret.size(), 0, (sockaddr*)&peer
            , len);
            if(n < 0)
            {
                LOG((int)LogLevel::FATAL) << "发送信息失败，服务器退出!";
                exit(1);
            }
        }
    }


private:
    int _socketfd = -1;
    func_t _f;
    // std::string _ip;
    // uint16_t _port;
    InetAddr _addr;
};